package com.touzhijia.authority.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.List;

/**
 * 作者： lzw<br/>
 * 创建时间：2018-03-14 14:45 <br/>
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private SecurityConfig securityConfig;
    @Autowired
    private UserLoginTokenAuthenticationProvider userLoginTokenAuthenticationProvider;
    @Autowired
    private UserLoginFilter userLoginFilter;
    @Autowired
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    @Autowired
    private AccessDecisionManager accessDecisionManager;
    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;
    @Autowired
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;

    /**
     * 认证配置
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.authenticationProvider(userLoginTokenAuthenticationProvider)
                .userDetailsService(customUserDetailsService);
    }

    /**
     * 全局请求忽略规则配置（比如说静态文件，比如说注册页面）<br/>
     * 全局HttpFirewall配置 <br/>
     * 是否debug配置 <br/>
     * 全局SecurityFilterChain配置 <br/>
     * privilegeEvaluator、expressionHandler、securityInterceptor、 <br/>
     */
    @Override
    public void configure(WebSecurity web) {
        // 配置忽略的路径
        List<String> ignored = securityProperties.getIgnored();
        if (securityConfig.getLogin().getLoginPage() != null) {
            ignored.add(securityConfig.getLogin().getLoginPage());
        }
        if (ignored != null && ignored.size() > 0) {
            web.ignoring().mvcMatchers(ignored.toArray(new String[ignored.size()]));
        }
    }

    /**
     * 具体的权限控制规则配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 自定义登录 Filter --> UserLoginFilter
        http.addFilterAt(userLoginFilter, UsernamePasswordAuthenticationFilter.class);

        // 过滤器配置
        http.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).accessDeniedHandler(customAccessDeniedHandler)
                .and()
                .authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager)
                .and()
                .formLogin().disable()
                .logout().logoutUrl(securityConfig.getLogout().getLogoutUrl()).logoutSuccessHandler(customLogoutSuccessHandler).permitAll()
                .and()
                .csrf().disable()
//                .sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true).sessionRegistry(sessionRegistry)
        ;
    }

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


}